#ifndef OCTOPOD_TCPSOCKET_H__
#define OCTOPOD_TCPSOCKET_H__

#include <QtGlobal>

#ifdef Q_OS_WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
extern "C" {
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
}
#endif  // Q_OS_WIN32

#include "socket.h" 

namespace octopod {

// underlying socket types/calls (for Windows support)
#ifdef Q_OS_WIN32
typedef SOCKET socket_t;
#define BAD_SOCKET INVALID_SOCKET
#define errno WSAGetLastError()
#else
typedef int socket_t;
#define BAD_SOCKET -1
#define SOCKET_ERROR -1

inline int closesocket(int sock) {
  return close(sock);
}
#endif  // Q_OS_WIN32

class TCPListenSocket : public ListenSocket {
  public:
    // Creates a TCP listen socket and the underlying state.
    TCPListenSocket();
    
    // Closes the TCP listen socket and cleans up the state.
    ~TCPListenSocket();

    // Begins listening on the listening socket.
    Socket::SocketError listen(uint16_t port);

    // Performs a blocking accept of a new TCP connection.
    Socket *accept();

  private:
    static const int kIncomingQueueLength = 15;

    socket_t listen_sock_;
    SocketState state_;

    DISALLOW_COPY_AND_ASSIGN(TCPListenSocket);
};

class TCPSocket : public Socket {
  public:
    // Creates a TCP transport socket.
    TCPSocket();
    ~TCPSocket();

    // Returns the current state of this socket.
    virtual SocketState state() const;

    // Attempts to connect; does not punch NAT holes
    virtual SocketError connect(const NetworkAddress &addr);

    // Attempts to disconnect.
    virtual SocketError disconnect();

    // Performs a blocking send.
    virtual int send(const char *data, int size);

    // Performs a blocking receive.
    virtual int recv(int size, char *data);

  private:
    socket_t sock_;
    SocketState state_;
    NetworkAddress::IPVersion ipversion_;

    friend class TCPListenSocket;
    DISALLOW_COPY_AND_ASSIGN(TCPSocket);
};


}  // namespace octopod

#endif  // OCTOPOD_TCPSOCKET_H__
